package controller;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.sql.ResultSet;
import java.sql.SQLException;

import view.AdminView;
import view.MainView;

import com.sun.rowset.CachedRowSetImpl;

public class ControllerAdminImpl implements ControllerAdmin {
	protected MainView main;
	protected AdminView av;
	private ObjectInputStream input;
	private ObjectOutputStream output;
	private Socket socket;
	private InetAddress addr = InetAddress.getByName(null);
	private int PORT = 1235;

	public ControllerAdminImpl(MainView m) throws SQLException, IOException {
		main = m;

	}

	@Override
	public void aggiungiCliente(String[] parametri) {

		av = main.getAdminView();
		try {
			if (!parametri[0].equals("") && !parametri[1].equals("")
					&& !parametri[2].equals("")) {
				String regex = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
				if (!parametri[2].matches(regex)) {
					av.mailSbagliata();
				} else {
					output.writeObject("generate");
					output.flush();
					String pass = (String) input.readObject();// la pass la
																// genero dal
																// serve.
					output.writeObject("aggiungiCliente_" + parametri[0] + "_"
							+ parametri[1] + "_" + parametri[2] + "_" + pass);
					output.flush();
					output.writeObject("ultimoIdCliente");
					output.flush();
					int id = (int) input.readObject();
					av.invioEmailOption();
					output.writeObject("segnalaRegistrazioneCliente_"
							+ parametri[2] + "_" + id + "_" + parametri[0]
							+ "_" + parametri[1] + "_" + pass);
					output.flush();
					av.clienteInserito(id, parametri[0], parametri[1], pass);
				}
			} else {
				av.inserireTuttiIParametri();
			}
		} catch (ClassNotFoundException | IOException w) {
			av.togliAggiungiCliente();
			main.erroreComunicazioneAdmin(false);

		}

	}

	@Override
	public void accedi(int idAdmin, String password) {
		try {
			av = main.getAdminView();
			socket = new Socket(addr, PORT);
			output = new ObjectOutputStream(socket.getOutputStream());
			input = new ObjectInputStream(socket.getInputStream());
			output.writeObject("getPassword_" + idAdmin);
			output.flush();
			String ris = (String) input.readObject();
			if (ris.equals(password)) {
				main.accessoRiuscitoAdmin(idAdmin);
			} else {
				if (ris.equals("null")) {
					main.erroreComunicazioneAdmin(socket.isConnected());
				} else {
					main.accessoNegato();
					socket.close();
				}
			}
		} catch (ClassNotFoundException | IOException w) {

			main.erroreComunicazioneAdmin(false);

		}
	}

	public void restituisciLibro(int idCliente, long isbn) {
		av = main.getAdminView();

		try {
			boolean flag;
			output.writeObject("hoIlLibro_" + idCliente + "_" + isbn);
			output.flush();
			flag = (boolean) input.readObject();
			if (flag) {
				output.writeObject("modificaDataEffettiva_" + idCliente + "_"
						+ isbn);
				output.flush();
				output.writeObject("incrementaCopie_" + isbn + "_" + idCliente);
				output.flush();
				output.writeObject("decrementaCopie_" + isbn + "_" + idCliente);
				output.flush();
				av.libroRestituito();
			} else {
				av.nonAppartiene();
			}
		} catch (IOException e) {
			av.togliRestituisci();
			main.erroreComunicazioneAdmin(false);
		} catch (ClassNotFoundException e) {
			av.togliRestituisci();
			main.erroreComunicazioneAdmin(false);
		}
	}

	public ResultSet cercaCliente(String[] parametri) {

		ResultSet ris = null;
		av = main.getAdminView();
		try {
			// String[] nomiParametri = { "idCliente", "nome", "cognome",
			// "email" };
			String regex = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
			for (int i = 0; i < 4; i++)
				if (parametri[i].length() < 1)
					parametri[i] = "null";
			if (parametri[3] != "null" && parametri[3].matches(regex)) {
				av.mailSbagliata();
			}
			if (parametri[0] != "null" || parametri[1] != "null"
					|| parametri[2] != "null" || parametri[3] != "null") {
			} else {

				av.inserireAlcuniParametri();
				return null;
			}
			output.writeObject("cercaCliente_" + parametri[0] + "_"
					+ parametri[1] + "_" + parametri[2] + "_" + parametri[3]);
			output.flush();
			CachedRowSetImpl crs = (CachedRowSetImpl) input.readObject();
			ris = crs.getOriginal();

		} catch (ClassNotFoundException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (SQLException e) {
			main.erroreComunicazioneAdmin(true);
		} catch (IOException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (NullPointerException e) {
			main.erroreComunicazioneAdmin(true);
		}
		return ris;
	}

	public ResultSet cercaLibro(String[] parametri) {
		ResultSet ris = null;
		av = main.getAdminView();
		try {

			for (int i = 0; i < 4; i++)
				if (parametri[i].length() < 2)
					parametri[i] = "null";
			if (parametri[0] != "null" || parametri[1] != "null"
					|| parametri[2] != "null" || parametri[3] != "null") {
			} else {

				av.inserireAlcuniParametri();
				return null;
			}
			output.writeObject("cercaLibro_" + parametri[0] + "_"
					+ parametri[1] + "_" + parametri[2] + "_" + parametri[3]);
			output.flush();
			CachedRowSetImpl crs = (CachedRowSetImpl) input.readObject();
			ris = crs.getOriginal();
			av.togliCercaLibro();
		} catch (ClassCastException e) {
			av.inserireAlcuniParametri();
		} catch (SQLException e) {
			main.erroreComunicazioneAdmin(true);
		} catch (IOException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (ClassNotFoundException e) {
			main.erroreComunicazioneAdmin(false);
		}
		return ris;
	}

	public ResultSet visualizzaStorico(String order) {
		ResultSet ris = null;
		try {
			output.writeObject("storicoClienti_" + order);
			output.flush();
			CachedRowSetImpl crs = (CachedRowSetImpl) input.readObject();
			ris = crs.getOriginal();
		} catch (IOException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (ClassNotFoundException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (SQLException ex) {
			main.erroreComunicazioneAdmin(true);
		}
		return ris;
	}

	public ResultSet visualizzaPreferiti(int numCopie) {
		ResultSet ris = null;
		try {
			output.writeObject("storicoClienti_" + numCopie);
			output.flush();
			CachedRowSetImpl crs = (CachedRowSetImpl) input.readObject();
			ris = crs.getOriginal();
		} catch (SQLException e) {
			main.erroreComunicazioneAdmin(true);
		} catch (IOException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (ClassNotFoundException e) {
			main.erroreComunicazioneAdmin(false);
		}
		return ris;
	}

	public void inviaSegnalazione(int i) {
		try {
			output.writeObject("clientiInScadenzaPrestito_" + i);
			output.flush();
			CachedRowSetImpl crs = (CachedRowSetImpl) input.readObject();
			ResultSet res = crs.getOriginal();
			while (res.next()) {
				String dataStimata = res.getString("dataStimata");
				int idClient = res.getInt("Cliente_idCliente");
				output.writeObject("getCredenziali_" + idClient);
				output.flush();
				long isbnLibro = res.getLong("Libri_isbn");
				output.writeObject("getInfoLibro_" + isbnLibro);
				output.flush();
				CachedRowSetImpl crs1 = (CachedRowSetImpl) input.readObject();
				ResultSet resLibro = crs1.getOriginal();
				resLibro.next();
				String titoloLibro = resLibro.getString("titolo");
				av.invioEmailOption();
				output.writeObject("segnalaRestituzione_" + titoloLibro + "_"
						+ isbnLibro + "_" + dataStimata);
				output.flush();
			}
		} catch (SQLException e) {
			main.erroreComunicazioneAdmin(socket.isConnected());
		} catch (IOException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (ClassNotFoundException e) {
			main.erroreComunicazioneAdmin(false);
		}
	}

	public ResultSet visualizzaClientiInRitardo() {
		ResultSet ris = null;
		try {
			output.writeObject("daRestituire");
			output.flush();
			CachedRowSetImpl crs = (CachedRowSetImpl) input.readObject();
			ris = crs.getOriginal();

		} catch (SQLException e) {
			main.erroreComunicazioneAdmin(socket.isConnected());
		} catch (IOException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (ClassNotFoundException e) {
			main.erroreComunicazioneAdmin(false);
		}
		return ris;
	}

	@Override
	public void prendiLibro(int idCliente, long isbn) {
		av = main.getAdminView();
		int copieCliente, copieBiblioteca;

		try {
			boolean flag;
			boolean flag2;
			output.writeObject("possoPrendereLibro_" + idCliente + "_" + isbn);
			output.flush();
			flag = (boolean) input.readObject();
			output.writeObject("disponibile_" + isbn);
			output.flush();
			flag2 = (boolean) input.readObject();
			output.writeObject("esiste_" + isbn);
			output.flush();
			boolean esisteLibro = (boolean) input.readObject();
			output.writeObject("esisteCliente_" + idCliente);
			output.flush();
			boolean esisteCliente = (boolean) input.readObject();
			if (esisteLibro && esisteCliente && flag) {
				output.writeObject("copieCliente_" + idCliente);
				output.flush();
				copieCliente = (int) input.readObject();
				output.writeObject("copieLibri_" + isbn);
				output.flush();
				copieBiblioteca = (int) input.readObject();

				if (copieCliente < 5 && copieBiblioteca > 0) {
					output.writeObject("decrementaCopie2_" + isbn);
					output.flush();
					output.writeObject("incrementaCopie2_" + idCliente);
					output.flush();
					output.writeObject("aggiungiLibroStorico_" + idCliente
							+ "_" + isbn);
					output.flush();
					av.libroPreso();
					output.writeObject("getDataStimata_" + isbn + "_"
							+ idCliente);
					output.flush();
					String finePrestitoString = (String) input.readObject();
					av.invioEmailOption();
					output.writeObject("getCredenziali_" + idCliente);
					output.flush();
					output.writeObject("segnalaConfermaPrestito_" + isbn + "_"
							+ finePrestitoString);
					output.flush();
				} else if (copieCliente > 4) {
					av.massimeCopieRaggiunte();
				} else if (!flag2) {

					av.libroTerminato();
				}

			} else {
				if (!esisteLibro || !esisteCliente)
					av.libroClienteInesistente();
				else
					av.NonPuoiPrendereLibro();
			}

		} catch (IOException e) {
			av.togliPrestito();
			main.erroreComunicazioneAdmin(false);
		} catch (ClassNotFoundException c) {
			av.togliPrestito();
			main.erroreComunicazioneAdmin(false);
		}
	}

	@Override
	public void aggiungiLibro(String[] par) {
		av = main.getAdminView();
		long isbn = 0;
		int numCopie = 0;
		boolean esiste = false;
		try {
			isbn = Long.parseLong(par[4]);
			numCopie = Integer.parseInt(par[6]);
			if (numCopie == 0) {
				av.numeroCopie();
				return;
			}
			output.writeObject("esiste_" + isbn);
			output.flush();
			esiste = (boolean) input.readObject();
			if (esiste) {
				output.writeObject("aggiornaCopie_" + numCopie + "_" + isbn);
				output.flush();
				av.aggiornateNumCopie();
			} else if (numCopie > 0) {
				if (!par[0].equals("") && !par[1].equals("")
						&& !par[2].equals("") && !par[3].equals("")) {
					if (par[5].length() < 1)
						par[5] = "null";
					if (par[7].length() < 1)
						par[7] = "null";
					if (par[5] != "null") {
						URL url = new URL(par[5]);
					}
					output.writeObject("aggiungiLibro_" + isbn + "_" + par[0]
							+ "_" + par[1] + "_" + par[2] + "_" + par[3] + "_"
							+ numCopie + "_" + par[5] + "_" + par[7]);
					output.flush();

					av.libroInserito();
				} else {
					av.inserireTuttiIParametri();
				}
			}
		} catch (NumberFormatException ex1) {
			av.datiScorretti();
		} catch (MalformedURLException ex) {
			av.erroreURL();
		} catch (IOException e) {
			main.erroreComunicazioneAdmin(false);
		} catch (ClassNotFoundException e) {
			main.erroreComunicazioneAdmin(false);
		}
	}

	public void chiudiConnessione() {
		try {
			socket.close();
		} catch (IOException e) {
		}
	}
}